
package com.idealighter.game.games.happyfive.struct;

import com.google.common.collect.Lists;

import com.idealighter.game.core.common.Game;
import com.idealighter.game.games.common.AbstractRoom;
import com.idealighter.game.games.common.AbstractSeat;
import com.idealighter.game.games.common.AbstractTable;
import com.idealighter.game.games.common.Card;
import com.idealighter.game.games.common.SeatState;
import com.idealighter.game.games.happyfive.manager.HappyFiveDataMgr;
import com.idealighter.game.games.happyfive.util.HandPower;
import com.idealighter.game.schedule.manager.ScheduleMgr;
import com.idealighter.game.server.context.ApplicationContext;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ScheduledFuture;

/**
 * 欢乐五张房间牌桌 .
 */
public class HappyFiveRoom extends AbstractRoom {

  // 房间中的桌子
  public final Map<Integer, Table> tables;

  public HappyFiveRoom(int id, String name, int tableNum) {
    super(id, name);
    this.tables = createTables(tableNum);
  }

  /**
   * 创建桌子 .
   * 
   * @param tableNum . 桌子数量
   * @return
   */
  private Map<Integer, Table> createTables(int tableNum) {
    Map<Integer, Table> tables = new LinkedHashMap<>(tableNum);
    for (int i = 0; i < tableNum; i++) {
      int tableId = id.intValue() * Table.MAX_TABLE + i + 1;

      Table table = new Table(tableId);
      tables.put(table.getId().intValue(), table);
    }

    return tables;
  }


  /**
   * 欢乐五张桌子 .
   */
  public class Table extends AbstractTable {
    // 最大桌子数
    public static final int MAX_TABLE = 100000;
    // 座位数量
    public static final int SEAT_NUM = 4;
    // 底注比率
    public static final double MIN_RATE = 2 / 100;
    // 所属房间
    public final HappyFiveRoom room = HappyFiveRoom.this;
    // 牌桌的座位
    public final List<Seat> seats;
    // 一副牌
    public final List<com.idealighter.game.games.happyfive.struct.cards.Card> cards =
        new HappyFiveCards().getCards();
    // 公共牌
    public List<com.idealighter.game.games.happyfive.struct.cards.Card> commonCards =
        Lists.newArrayList();
    // 当前最大注
    public long maxBet = 0;
    // 加注数
    public long raiseBet = 0;
    // 计时器
    public ScheduleMgr scheduleMgr = null;
    // 阶段(0发牌，1第一轮下注,2发公共牌3张,3第二轮下注,4第二次发牌,5第三轮下注，6第三次发牌，7第四轮下注, 8,结束，结算)
    public int state = 0;
    // 牌序
    public int cardIndex = 0;
    // 庄家位置
    public byte landlordOrder = 0;
    // 下一个玩家位置
    public int nextPlayOrder = -1;
    // 当前下注的玩家的位置
    public int curOrder = -1;
    // 总下注筹码数
    public int totalChips = 0;
    // 发牌是否结束
    public boolean isdealCardOver = false;
    // 玩家退出时遗留下来的筹码
    public long exitChips = 0;
    // 准备人数->防止一人准备就发牌
    public int readyCount = 0;
    // 是否在游戏中
    public boolean isGaming = false;
    // 上一个人下注时，玩家筹码是否相等
    public boolean preBet = true;
    public long minBet = 0;
    // 是否立刻结算
    public boolean isBanlance = false;

    /**
     * 构造函数.
     * 
     * @param id .
     */
    private Table(int id) {
      super(id);
      this.seats = createSeats();
    }

    @SuppressWarnings("unchecked")
    @Override
    public HappyFiveRoom room() {
      return room;
    }


    /**
     * 计算最小筹码数 .
     *
     * @return
     */
    public long minBet() {
      long minBet = 0;
      for (Seat seat : seats) {
        if (seat.getPlayerId() == 0) {
          continue;
        }
        if (seat.isFold) {
          continue;
        }
        if (minBet == 0) {
          minBet = seat.getTotalChips();
        }
        if (seat.getTotalChips() <= minBet) {
          minBet = seat.getTotalChips();
        }
      }
      this.minBet = minBet;
      return this.minBet;
    }

    /**
     * 从最大明牌的玩家开始加注 .
     */
    public int firstOrder() {
      int order = 0;
      for (Seat seat : seats) {
        if (seat.getPlayerId() == 0) {
          continue;
        }
        for (Seat seat1 : seats) {
          if (seat1.getPlayerId() == 0) {
            continue;
          }
          if (seat.getPlayerId() == seat1.getPlayerId()) {
            continue;
          }
          if (seat.cards.get(0).getNumber().getPower() >= seat1.cards.get(0).getNumber()
              .getPower()) {
            if (seat.cards.get(0).getNumber().getPower() == seat1.cards.get(0).getNumber()
                .getPower()) {
              if (seat.cards.get(0).getSuit().getPower() > seat1.cards.get(0).getSuit()
                  .getPower()) {
                order = seat.getOrder();
                continue;
              }
            }
            order = seat.getOrder();
          }
        }
      }
      return order;
    }

    /**
     * 下一个位置order .
     * 
     * @param seat 座位信息.
     * @return
     */
    public int nextSeatOrder(Seat seat) {
      int order = seat.getOrder();
      Seat nextSeat;
      for (int i = 0; i < seats.size(); i++) {
        order += 1;
        if (order > seats.size()) {
          order -= seats.size();
        }
        nextSeat = seats.get(order - 1);
        if (nextSeat.getPlayerId() > 0 && nextSeat.isFold == false) {
          return nextSeat.getOrder();
        }
      }
      return 1;
    }

    /**
     * 下一个位置order .
     * 
     * @param order .
     * @return
     */
    public int nextSeatOrder(int order) {
      Seat nextSeat;
      for (int i = 0; i < seats.size(); i++) {
        order += 1;
        if (order > seats.size()) {
          order -= seats.size();
        }
        nextSeat = seats.get(order - 1);
        if (nextSeat.getPlayerId() > 0 && nextSeat.isFold == false) {
          return nextSeat.getOrder();
        }
      }
      return 1;
    }

    /**
     * 下一个位置 .
     * 
     * @param seat 座位信息.
     * @return
     */
    public Seat nextSeat(Seat seat) {
      return seats.get(nextSeatOrder(seat));
    }

    /**
     * 上一个位置 .
     * 
     * @param seat 座位信息.
     * @return
     */
    public Seat preSeat(Seat seat) {
      return seats.get(nextSeatOrder(seat));
    }

    /**
     * 上一个位置坐标 .
     *
     * @param seat 座位信息.
     * @return
     */

    public int preSeatOrder(Seat seat) {
      int index = seat.getOrder() - 1;
      if (index <= 0) {
        index += seats.size();
      }
      for (int i = index; i <= seats.size(); i++) {
        if (seats.get(index - 1).getPlayerId() == 0 || seats.get(index - 1).isAllIn
            || seats.get(index - 1).isFold) {
          index--;
        } else {
          return index;
        }
      }

      return index;
    }

    /**
     * 获取牌桌的庄家的位置 .
     * 
     * @return
     */
    public Seat landlord() {
      for (Seat seat : seats) {
        if (seat.landlord) {
          return seat;
        }
      }

      return null;
    }

    /**
     * 创建座位 .
     * 
     * @return
     */
    private List<Seat> createSeats() {
      List<Seat> seats = new ArrayList<>();
      for (byte i = 1; i <= SEAT_NUM; i++) {
        seats.add(new Seat(i));
      }

      return Collections.unmodifiableList(seats);
    }

    /**
     * 重置牌桌 .
     */
    public void reset() {
      this.nextPlayOrder = -1;
      this.raiseBet = 0;
      this.curOrder = -1;
      // this.isdealCardOver = false;
      this.exitChips = 0;
      this.readyCount = 0;
      this.isGaming = false;
      this.cardIndex = 0;
      this.totalChips = 0;
      this.minBet = 0;
      this.preBet = true;
      this.maxBet = 0;
      this.commonCards.clear();
      this.isBanlance = false;
    }

    /**
     * . 欢乐五张座位 .
     * 
     * @date 2015年8月7日 上午1:37:40
     */
    public class Seat extends AbstractSeat {
      // 所属桌子
      public final Table table = Table.this;
      // 牌数据->手牌
      public final List<com.idealighter.game.games.happyfive.struct.cards.Card> cards =
          Lists.newArrayList();
      // 玩家手中的明牌
      public List<com.idealighter.game.games.happyfive.struct.cards.Card> lightCards =
          Lists.newArrayList();
      // 是否准备好
      public boolean ready = false;
      // 是否托管
      public boolean hosted = false;
      // 是否是庄家
      public boolean landlord = false;
      // 出牌次数
      public int playNum = 0;
      // 玩家是否加倍
      public boolean doubled = false;
      // 玩家总下注筹码
      public long bet = 0;
      // 玩家总下注筹码->临时存储
      public long tempbet = 0;
      // 玩家当前轮次的下注数
      public int curBet = 0;

      public List<Integer> betList = Lists.newArrayList();
      // 玩家结算筹码
      public long billBet = 0;
      // 玩家总筹码
      // public int totalChips = 0;
      // 是否梭哈
      public boolean isAllIn = false;
      // 是否弃牌
      public boolean isFold = false;
      // 是否有一次操作
      public boolean isBet = false;
      // 是否加注过
      public boolean isRaise = false;
      // 结算牌大小
      public HandPower handPower = null;
      // 明牌牌值大小
      public int lightPower = 0;

      // 结算的大小
      public int power = 0;
      // 临时存储
      public long tempTotal = 0;

      // 牌是否最大(用于机器人控制)
      public int isWin = 0;
      // 是否系统托管(已放弃)
      public boolean systemHosted = false;
      public ScheduledFuture<?> stepFuture = null;

      public Seat(byte order) {
        super(order);
      }

      public int getPower() {
        return power;
      }


      @Override
      public boolean equals(Object obj) {
        if (!(obj instanceof Card)) {
          return false;
        }
        Seat other = (Seat) obj;
        return order == other.order;
      }

      @SuppressWarnings("unchecked")
      @Override
      public Table table() {
        return table;
      }


      /**
       * 重置座位数据 .
       */
      public void reset() {
        this.ready = false;
        this.landlord = false;
        this.hosted = false;
        this.playNum = 0;
        this.doubled = false;
        this.lightCards.clear();
        this.cards.clear();
        this.isFold = false;
        this.isAllIn = false;
        this.isBet = false;
        this.power = 0;
        this.lightPower = 0;
        this.isRaise = false;
        this.handPower = null;
        this.billBet = 0;
        this.tempbet = 0;
        this.bet = 0;
        this.curBet = 0;
        this.state = SeatState.SEATED;
        this.betList.clear();
        this.tempTotal = 0;
        this.isWin = 0;
        this.totalChips = 0;
      }

      /**
       * 重置座位数据除了准备 .
       */
      public void resetButReady() {
        this.landlord = false;
        this.hosted = false;
        this.playNum = 0;
        this.doubled = false;
        this.cards.clear();
      }

      /**
       * 重置座位数据除了totalChips .
       */
      public void resetButTotalChips() {
        long totalChips = this.totalChips;
        reset();
        this.totalChips = totalChips;
      }


      /**
       * 清空座位数据 .
       */
      public void clear() {
        this.playerId = 0;
        this.playerName = null;
        reset();
      }

    }

    @Override
    public Collection<Long> players() {
      Set<Long> players = new HashSet<>();
      for (Seat seat : seats) {
        if (seat.getPlayerId() > 0) {
          players.add(seat.getPlayerId());
        }
      }
      return players;
    }

    @Override
    public List<AbstractSeat> seats() {
      return new ArrayList<>(seats);
    }
  }

  @Override
  public Game game() {
    return Game.HAPPY_FIVE;
  }

  @Override
  public AbstractSeat seat(long playerId) {
    return ApplicationContext.getBean(HappyFiveDataMgr.class).getPlayerSeat(playerId);
  }

  @Override
  public Collection<? extends AbstractTable> tables() {
    return tables.values();
  }

}
